package org.smart4j.framework.proxy;

/**
 * Created by liangyue on 2018/1/8.
 */

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smart4j.framework.annotation.Transaction;
import org.smart4j.framework.helper.DatabaseHelper;

import java.lang.reflect.Method;

/**
 * 事务代理类
 */
public class TransactionProxy implements Proxy {
	private static final Logger LOGGER = LoggerFactory.getLogger(TransactionProxy.class);

	/**
	 * FLAG_HOLDER为本地线程变量，
	 * 保证在同一线程中，事务控制的相关逻辑只会执行一次
	 */
	private static final ThreadLocal<Boolean> FLAG_HOLDER = new ThreadLocal<Boolean>(){
		@Override
		protected Boolean initialValue(){
			return false;
		}
	};

	@Override
	public Object doProxy(ProxyChain proxyChain) throws Throwable{
		Object result;
		boolean flag = FLAG_HOLDER.get();
		Method method = proxyChain.getTargetMethod();
		if (!flag && method.isAnnotationPresent(Transaction.class)){
			FLAG_HOLDER.set(true);
			try {
				DatabaseHelper.beginTransaction();
				LOGGER.debug("begin transaction");
				result = proxyChain.doProxyChain();
				DatabaseHelper.commitTransaction();
				LOGGER.debug("commit transaction");
			} catch (Exception e) {
				DatabaseHelper.rollbackTransaction();
				LOGGER.debug("roll back transaction");
				throw e;
			}finally {
				FLAG_HOLDER.remove();
			}

		}
		else {
			result = proxyChain.doProxyChain();
		}
		return result;

	}
}
